package com.employment.controller;

import com.employment.dto.Result;
import com.employment.entity.User;
import com.employment.security.JwtTokenUtil;
import com.employment.security.UserPrincipal;
import com.employment.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import java.util.HashMap;
import java.util.Map;

/**
 * 认证控制器
 * 
 * @author Employment System
 * @since 1.0.0
 */
@Tag(name = "用户认证", description = "用户认证相关接口")
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {

    private final AuthenticationManager authenticationManager;
    private final JwtTokenUtil jwtTokenUtil;
    private final UserService userService;
    private final PasswordEncoder passwordEncoder;

    @Operation(summary = "用户登录", description = "用户登录获取访问令牌")
    @PostMapping("/login")
    public Result<Map<String, Object>> login(@Validated @RequestBody LoginRequest loginRequest) {
        try {
            // 进行身份认证
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            loginRequest.getUsername(),
                            loginRequest.getPassword()
                    )
            );

            UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();

            // 生成JWT令牌
            Map<String, Object> claims = new HashMap<>();
            claims.put("userId", userPrincipal.getUserId());
            claims.put("userType", userPrincipal.getUserType());
            
            String token = jwtTokenUtil.generateToken(userPrincipal.getUsername(), claims);

            // 更新最后登录信息
            userService.updateLastLoginInfo(userPrincipal.getUserId(), loginRequest.getClientIp());

            // 返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("token", token);
            result.put("tokenType", "Bearer");
            result.put("expiresIn", 7 * 24 * 3600); // 7天
            result.put("user", userPrincipal);

            return Result.success("登录成功", result);
        } catch (Exception e) {
            return Result.error("用户名或密码错误");
        }
    }

    @Operation(summary = "用户注册", description = "用户注册新账户")
    @PostMapping("/register")
    public Result<User> register(@Validated @RequestBody RegisterRequest registerRequest) {
        try {
            // 检查用户名是否已存在
            if (userService.existsByUsername(registerRequest.getUsername())) {
                return Result.badRequest("用户名已存在");
            }

            // 检查邮箱是否已存在
            if (userService.existsByEmail(registerRequest.getEmail())) {
                return Result.badRequest("邮箱已被注册");
            }

            // 检查手机号是否已存在
            if (userService.existsByPhone(registerRequest.getPhone())) {
                return Result.badRequest("手机号已被注册");
            }

            // 创建新用户
            User user = new User();
            user.setUsername(registerRequest.getUsername());
            user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
            user.setEmail(registerRequest.getEmail());
            user.setPhone(registerRequest.getPhone());
            user.setUserType(registerRequest.getUserType());
            user.setRealName(registerRequest.getRealName());
            user.setStatus(1); // 默认启用

            boolean success = userService.createUser(user);
            if (success) {
                return Result.success("注册成功", user);
            }
            return Result.error("注册失败");
        } catch (Exception e) {
            return Result.error("注册失败：" + e.getMessage());
        }
    }

    @Operation(summary = "退出登录", description = "用户退出登录")
    @PostMapping("/logout")
    public Result<Void> logout(@AuthenticationPrincipal UserPrincipal userPrincipal) {
        // TODO: 可以将token加入黑名单
        return Result.success("退出成功");
    }

    @Operation(summary = "刷新令牌", description = "刷新访问令牌")
    @PostMapping("/refresh")
    public Result<Map<String, Object>> refreshToken(@RequestHeader("Authorization") String authHeader) {
        try {
            String token = authHeader.substring(7); // 移除"Bearer "前缀
            String newToken = jwtTokenUtil.refreshToken(token);

            Map<String, Object> result = new HashMap<>();
            result.put("token", newToken);
            result.put("tokenType", "Bearer");
            result.put("expiresIn", 7 * 24 * 3600);

            return Result.success("令牌刷新成功", result);
        } catch (Exception e) {
            return Result.error("令牌刷新失败");
        }
    }

    @Operation(summary = "获取当前用户信息", description = "获取当前登录用户的详细信息")
    @GetMapping("/me")
    public Result<UserPrincipal> getCurrentUser(@AuthenticationPrincipal UserPrincipal userPrincipal) {
        return Result.success(userPrincipal);
    }

    @Operation(summary = "修改密码", description = "修改当前用户密码")
    @PostMapping("/change-password")
    public Result<Void> changePassword(@Validated @RequestBody ChangePasswordRequest request,
                                     @AuthenticationPrincipal UserPrincipal userPrincipal) {
        try {
            boolean success = userService.changePassword(
                    userPrincipal.getUserId(),
                    request.getOldPassword(),
                    request.getNewPassword()
            );
            
            if (success) {
                return Result.success("密码修改成功");
            }
            return Result.error("原密码错误");
        } catch (Exception e) {
            return Result.error("密码修改失败：" + e.getMessage());
        }
    }

    @Operation(summary = "重置密码", description = "通过邮箱重置密码")
    @PostMapping("/reset-password")
    public Result<Void> resetPassword(@Validated @RequestBody ResetPasswordRequest request) {
        try {
            boolean success = userService.resetPassword(request.getEmail(), request.getVerificationCode(), request.getNewPassword());
            if (success) {
                return Result.success("密码重置成功");
            }
            return Result.error("验证码错误或已过期");
        } catch (Exception e) {
            return Result.error("密码重置失败：" + e.getMessage());
        }
    }

    @Operation(summary = "发送验证码", description = "发送邮箱验证码")
    @PostMapping("/send-verification-code")
    public Result<Void> sendVerificationCode(@RequestParam String email) {
        try {
            boolean success = userService.sendVerificationCode(email);
            if (success) {
                return Result.success("验证码发送成功");
            }
            return Result.error("验证码发送失败");
        } catch (Exception e) {
            return Result.error("验证码发送失败：" + e.getMessage());
        }
    }

    /**
     * 登录请求DTO
     */
    @Data
    public static class LoginRequest {
        @NotBlank(message = "用户名不能为空")
        private String username;

        @NotBlank(message = "密码不能为空")
        private String password;

        private String clientIp;
    }

    /**
     * 注册请求DTO
     */
    @Data
    public static class RegisterRequest {
        @NotBlank(message = "用户名不能为空")
        @Pattern(regexp = "^[a-zA-Z0-9_]{4,20}$", message = "用户名格式不正确")
        private String username;

        @NotBlank(message = "密码不能为空")
        @Pattern(regexp = "^.{6,20}$", message = "密码长度为6-20位")
        private String password;

        @NotBlank(message = "邮箱不能为空")
        @Email(message = "邮箱格式不正确")
        private String email;

        @NotBlank(message = "手机号不能为空")
        @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
        private String phone;

        @NotBlank(message = "真实姓名不能为空")
        private String realName;

        private Integer userType = 1; // 默认为求职者
    }

    /**
     * 修改密码请求DTO
     */
    @Data
    public static class ChangePasswordRequest {
        @NotBlank(message = "原密码不能为空")
        private String oldPassword;

        @NotBlank(message = "新密码不能为空")
        @Pattern(regexp = "^.{6,20}$", message = "新密码长度为6-20位")
        private String newPassword;
    }

    /**
     * 重置密码请求DTO
     */
    @Data
    public static class ResetPasswordRequest {
        @NotBlank(message = "邮箱不能为空")
        @Email(message = "邮箱格式不正确")
        private String email;

        @NotBlank(message = "验证码不能为空")
        private String verificationCode;

        @NotBlank(message = "新密码不能为空")
        @Pattern(regexp = "^.{6,20}$", message = "新密码长度为6-20位")
        private String newPassword;
    }
}